#include "buzzer.h"
#include <QThread>
#include <QMutex>
#include <QFile>
#include "systempreset.h"
#include "constants.h"
#include "audiomanager.h"
#include "logger.h"

#define MAX_TRY_PLAY_TIMES 10

class BuzzerPrivate : public QThread
{
public:
    BuzzerPrivate() { init(); }
    ~BuzzerPrivate() { exit(); }

    void start();
    void stop();
    void setVolume(int value);
    void setWavfile(const QString &file);

private:
    bool startRing();
    bool stopRing();
    void exit();
    void init();

protected:
    void run();

private:
    QMutex m_mutex;
    volatile bool m_stop;
    int m_playFailTimes;
    int m_cardId;
    int m_deviceId;
    int m_audioVolume; // 音量
    QString m_audioFile; // 音频文件
};

Buzzer *Buzzer::instance()
{
    static Buzzer inst;
    return &inst;
}

Buzzer::Buzzer()
{
    d = new BuzzerPrivate;
}

Buzzer::~Buzzer()
{
    delete d;
}

void Buzzer::start()
{
    d->start();
}

void Buzzer::stop()
{
    d->stop();
}

void Buzzer::setVolume(int value)
{
    d->setVolume(value);
}

void Buzzer::setAudiofile(const QString &wavFile)
{
    d->setWavfile(wavFile);
}

bool BuzzerPrivate::startRing()
{
    return AudioManager::play(m_audioFile, m_cardId, m_deviceId);
}

bool BuzzerPrivate::stopRing()
{
    return AudioManager::stop();
}

void BuzzerPrivate::start()
{
    if (!this->isRunning())
    {
        QMutexLocker locker(&m_mutex);
        if (!this->isRunning())
        {
            m_stop = false;
            QThread::start();
        }
    }
}

void BuzzerPrivate::stop()
{
    QMutexLocker locker(&m_mutex);
    m_stop = true;
    stopRing();
}

void BuzzerPrivate::exit()
{
    stop();
    quit();
    wait();
}

void BuzzerPrivate::init()
{
    m_cardId = SystemPreset::instance()->getIntData(EnumPresetItem::BuzzerCardId);
    m_deviceId = SystemPreset::instance()->getIntData(EnumPresetItem::BuzzerDeviceId);
    m_audioVolume = SystemPreset::instance()->getIntData(EnumPresetItem::BuzzerAudioVolume);
    m_audioFile = AudioDir + SystemPreset::instance()->getStringData(EnumPresetItem::BuzzerAudioFile);
    setVolume(m_audioVolume);
}

void BuzzerPrivate::setVolume(int value)
{
    QMutexLocker locker(&m_mutex);
    int volume = qMin(qMax(0, value), 100);
    if (volume != m_audioVolume)
    {
        AudioManager::setVolume(volume, m_cardId);
    }
}

void BuzzerPrivate::setWavfile(const QString &file)
{
    QMutexLocker locker(&m_mutex);
    QString audioFile = AudioDir + file;
    if (QFile::exists(audioFile) && m_audioFile != audioFile)
    {
        m_audioFile = audioFile;
        if (this->isRunning())
        {
            stopRing();
            startRing();
        }
    }
}

void BuzzerPrivate::run()
{
    m_playFailTimes = 0;

    while (!m_stop)
    {
        if (!startRing())
        {// 停止单次播放
            if (!m_stop)
            {// 播放失败
                m_playFailTimes++;
                QThread::msleep(1000);
                if (m_playFailTimes > MAX_TRY_PLAY_TIMES)
                {// 连续10s播放失败，停止
                    sysDebug("BuzzerPrivate::run() interrupted: play timeout %ds", MAX_TRY_PLAY_TIMES);
                    break;
                }
            }
            else
            {
                m_playFailTimes = 0;
            }
        }
    }
}
